package com.heo.music.player.service.impl;

import com.heo.music.player.config.MusicStorageConfig;
import com.heo.music.player.config.UploadConfig;
import com.heo.music.player.converter.MusicInfoConverter;
import com.heo.music.player.dao.MusicInfoDao;
import com.heo.music.player.dto.input.MusicInfoInput;
import com.heo.music.player.dto.output.MusicInfoOutput;
import com.heo.music.player.dto.output.PageOutput;
import com.heo.music.player.dto.query.MusicInfoQuery;
import com.heo.music.player.entity.MusicInfo;
import com.heo.music.player.service.MusicInfoService;
import com.heo.music.player.util.FileUtils;
import com.heo.music.player.util.MusicDurationCalculator;
import lombok.RequiredArgsConstructor;
import org.modelmapper.ModelMapper;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * created on 2024-05-11 11:40
 *
 * @author 星天无极
 **/
@Service
@RequiredArgsConstructor
public class MusicInfoServiceImpl implements MusicInfoService {

    private final MusicInfoDao musicInfoDao;

    private final MusicInfoConverter musicInfoConverter;

    private final ModelMapper modelMapper;

    private final UploadConfig uploadConfig;

    private final MusicStorageConfig musicStorageConfig;

    @Override
    public PageOutput<MusicInfoOutput> findAllMusicInfo(MusicInfoQuery musicInfoQuery) {
        Pageable pageable = musicInfoQuery.convertPageable();
        Specification<MusicInfo> spec = musicInfoQuery.convertSpec();
        Page<MusicInfo> page = musicInfoDao.findAll(spec, pageable);
        return musicInfoConverter.convert(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MusicInfoOutput createMusicInfo(MusicInfoInput musicInfoInput) throws IOException {
        MusicInfo musicInfo = modelMapper.map(musicInfoInput, MusicInfo.class);
        String title = musicInfo.getTitle();
        String artist = musicInfo.getArtist();
        // 检查标题和歌手
        if (musicInfoDao.existsByTitleAndArtist(musicInfo.getTitle(), musicInfo.getArtist())) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "音乐信息重复");
        }

        // 设置音乐文件
        {
            String filePath = musicInfoInput.getFilePath();
            Path tmpFile = Paths.get(uploadConfig.getPath(), filePath);
            if (!tmpFile.toFile().exists() || !tmpFile.toFile().isFile()) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "音乐文件不存在");
            }

            int duration = MusicDurationCalculator.getDuration(tmpFile.toFile());
            musicInfo.setDuration(duration);
            String suffixName = FileUtils.getSuffixName(musicInfo.getFilePath());
            filePath = musicStorageConfig.getMusicDir() + "/" + title + "-" + artist + suffixName;
            Path file = Paths.get(musicStorageConfig.getPath(), filePath);
            if (file.toFile().exists()) {
                file.toFile().delete();
            }
            Files.move(tmpFile, file);
            musicInfo.setFilePath(filePath);
        }
        // 设置封面
        {
            String coverPath = musicInfo.getCoverPath();
            if (coverPath != null) {
                Path tmpFile = Paths.get(uploadConfig.getPath(), coverPath);
                if (!tmpFile.toFile().exists() || !tmpFile.toFile().isFile()) {
                    throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "音乐文件不存在");
                }
                String suffixName = FileUtils.getSuffixName(musicInfo.getCoverPath());
                coverPath = musicStorageConfig.getCoverDir() + "/" + title + "-" + artist + suffixName;
                Path file = Paths.get(musicStorageConfig.getPath(), coverPath);
                if (file.toFile().exists()) {
                    file.toFile().delete();
                }
                Files.move(tmpFile, file);
                musicInfo.setCoverPath(coverPath);
            }
        }
        // 设置歌词
        {
            String lyricsPath = musicInfo.getLyricsPath();
            if (lyricsPath != null) {
                Path tmpFile = Paths.get(uploadConfig.getPath(), lyricsPath);
                if (!tmpFile.toFile().exists() || !tmpFile.toFile().isFile()) {
                    throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "音乐文件不存在");
                }
                String suffixName = FileUtils.getSuffixName(musicInfo.getLyricsPath());
                lyricsPath = musicStorageConfig.getLyricsDir() + "/" + title + "-" + artist + suffixName;
                Path file = Paths.get(musicStorageConfig.getPath(), lyricsPath);
                if (file.toFile().exists()) {
                    file.toFile().delete();
                }
                Files.move(tmpFile, file);
                musicInfo.setLyricsPath(lyricsPath);
            }
        }
        musicInfoDao.save(musicInfo);
        return musicInfoConverter.convert(musicInfo);
    }

    @Override
    public void deleteMusicInfo(Integer id) {
        musicInfoDao.findById(id).ifPresent(musicInfo -> {
            musicInfo.setIsDeleted(true);
            musicInfoDao.save(musicInfo);
        });
    }
}
